package com.wandian.executor;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import com.wandian.texas.BaseCommandObject;
import com.wandian.util.ArrayList;
import com.wandian.util.ConsoleTable;
import com.wandian.util.Log;
import com.wandian.util.TimeWatch;

/**
 * @author long
 * @Create 2012-10-11 下午2:09:58
 * @QQ 108232706
 * @version 1.0
 * @description TimerPool
 */
public class TimerPool {

	private static ArrayList<TimerThread> timerThreaLlist = null;
	private static BlockingQueue<BaseCommandObject> workQueue = null;
	private static boolean isInit = false;
	// corePoolSize the number of threads
//	private static int corePoolSize;
	// 负责执行命令的线程空闲，表明可以调度唤醒
	private static final int idle_status = 0;
	// 负责执行命令的线程正在执行命令，表明忙
	private static final int ready_exec_status = 1;

	public static final int INFREELIST = 0;// 命令，在空闲资源里
	public static final int INADDTOUSELIST = 1;// 命令， 加入使用资源
	public static final int RUNNINGCMD = 2;// 命令， 已分配thread执行状态
	public static final int COMPLETECMD = 3;// 命令， thread执行execute完成状态
	private static Thread dispatchProcessThread;// 是否初始化线程池
	private static boolean isStarted = false;// 是否开始监视

	public synchronized static boolean start(int _corePoolSize) {
		if (!isStarted) {
			if (!isInit) {

				workQueue = new LinkedBlockingQueue<BaseCommandObject>();
				isInit = true;
			}
//			corePoolSize = _corePoolSize;
			timerThreaLlist = new ArrayList<TimerThread>("ThreadPool_cmdThreaLlist", _corePoolSize, false, false);
			int count = 0;
			TimerThread timerThread;
			do {
				timerThread = new TimerThread(count);
				timerThread.setIdle();
				timerThreaLlist.add(timerThread);
				timerThread.start();
				count++;
			} while (count < _corePoolSize);
			dispatchProcessThread = new Thread("dispatchProcessThread") {
				@Override
				public void run() {
					MainProcessor();
				}
			};
			dispatchProcessThread.start();
			isStarted = true;
		}
		return true;
	}

	/** 停止线程池轮询 */
	public static void stop()
	{
		// if (isInit) {
		isStarted = false;
		stopTimerThread();
		// }
	}

	public static boolean Add(BaseCommandObject command) throws InterruptedException {
		return workQueue.offer(command);
	}

	// TimerCommand ad；
	// Add.runtime = GettickCount()+1000;
	public static void MainProcessor() {
		/*
		 * currenttime; for(begin end ++) { if(runtime >= currenttime) {
		 * TimerRunFun(timerid); count++; runtime = currenttime+1000; }
		 * 
		 * }
		 */
		do {
			try {
				TimerThread cmdThread = getIdleCmdThread();
				if (cmdThread != null) {
					TimerCommand command = (TimerCommand) workQueue.poll(3, TimeUnit.SECONDS);
					if (command != null) {
						// 将当前命令的状态设置成正在在执行状态
						command.setCmdstatus(RUNNINGCMD);
						// 给执行命令的专门线程指定命令
						cmdThread.setRunFun(command);
					}
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}// 阻塞
		} while (isStarted);
	}

	public static void printThreadPoolStatus() {
		ConsoleTable t = new ConsoleTable(8, true);
		t.appendRow();
		t.appendColum("序号").appendColum("线程id").appendColum("状态").appendColum("执行命令数").appendColum("max run time").appendColum("max run cmdid").appendColum("min run time")
				.appendColum("min run cmdid");
		int count = 0;
		TimerThread cmdThread;
		for (int i = 0; i < timerThreaLlist.size(); i++) {
			cmdThread = timerThreaLlist.get(i);
			count++;
			t.appendRow();
			t.appendColum(count).appendColum(cmdThread.getName()).appendColum(cmdThread.getThreadStatus()).appendColum(cmdThread.getCmdCount()).appendColum(cmdThread.getMaxTime())
					.appendColum(cmdThread.maxCmdId).appendColum(cmdThread.getMinTime()).appendColum(cmdThread.minCmdId);
		}
		Log.info(t.toString());
	}

	/**
	 * 返回专门执行命令线程中一个空闲的线程
	 * 
	 * @return
	 */
	private static TimerThread getIdleCmdThread() {
		for (int i = 0; i < timerThreaLlist.size(); i++) {
			if (timerThreaLlist.get(i).getCmdStatus() == idle_status)
				return timerThreaLlist.get(i);
		}
		return null;
	}

	/**
	 * *
	 * 
	 * @return
	 */
	private static void stopTimerThread() {
		if (timerThreaLlist == null)
			return;
		for (int i = 0; i < timerThreaLlist.size(); i++) {
			timerThreaLlist.get(i).setRun(false);

		}
	}

	static class TimerThread extends Thread {
		private boolean isRun;
//		private int count;
		private TimerCommand cmdObject;
		private int _status;
		private final TimeWatch timeWatch;
		private long maxTime = 0L;
		private long minTime = 0L;
		private short maxCmd = 0;
		public String maxCmdId;
		public String minCmdId;
		private short minCmd = 0;
		private int cmdCount = 0;

		public boolean isRun() {
			return isRun;
		}

		public void setRun(boolean isRun) {
			this.isRun = isRun;
		}

		public TimerThread(int index) {
			super("TimerThread" + index);
			timeWatch = new TimeWatch("TimerThread" + index + "执行定时操作");
			isRun = true;
			_status = idle_status;
		}

		public void setRunFun(TimerCommand _cmdObject)
		{
			this.cmdObject = _cmdObject;
			setRunReady();
		}

		public void setRunReady() {
			_status = ready_exec_status;
		}

		public void setIdle() {
			_status = idle_status;
		}

		public int getCmdStatus() {
			return _status;
		}

		/**
		 * 获取线程当前状态
		 * 
		 * @return
		 */
		public String getThreadStatus() {
			switch (_status) {
			case idle_status:
				return "空闲";
			case ready_exec_status:
				return "忙碌:" + this.cmdObject.getCmd();

			default:
				return "未知";
			}
		}

		private void getComandFun() {
			try {
				do {
					sleep(this.cmdObject.initialDelay);
					// this.cmdObject.command.run();//换成根据命令id去执行
					this.cmdObject.currentCount++;
				} while (this.cmdObject.totalCount != 0 && (this.cmdObject.currentCount < this.cmdObject.totalCount));
			} catch (Exception e) {
				Log.error("Handler execute has exception:", e);
			}
			Log.debug("执行命令完毕:" + this.cmdObject.name);
			// 将当前命令设置成执行完成，以便线程池能回收此资源
			cmdObject.setCmdstatus(COMPLETECMD);
		}

		private void setMaxMinTime() {
			cmdCount++;
			if (cmdCount == 1) {
				this.setMaxTime(timeWatch.getSpendTime());
				this.setMinTime(timeWatch.getSpendTime());
				this.setMinCmd(this.cmdObject.getCmd());
				this.maxCmdId = this.cmdObject.name;
				this.minCmdId = this.cmdObject.name;
				this.setMaxCmd(this.cmdObject.getCmd());
			}
			if (timeWatch.getSpendTime() > this.getMaxTime()) {
				this.setMaxTime(timeWatch.getSpendTime());
				this.setMaxCmd(this.cmdObject.getCmd());
				this.maxCmdId = this.cmdObject.name;
			} else if (timeWatch.getSpendTime() < this.getMinTime()) {
				this.setMinTime(timeWatch.getSpendTime());
				this.setMinCmd(this.cmdObject.getCmd());
				this.minCmdId = this.cmdObject.name;
			}
		}

		@Override
		public void run() {
			while (isRun)
			{
				if (_status == ready_exec_status)
				{
					timeWatch.start();
					// 根据cmd，data，执行命令
					getComandFun();
					// 执行完之后，此线程设置为空闲，以供TheadPool调度给新来的命令列表
					timeWatch.stop(true, 2000L);// 如果超过2秒，警告
					setMaxMinTime();
					timeWatch.reset();
					_status = idle_status;
				}
				try {
					TimeUnit.MILLISECONDS.sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

		public int getCmdCount() {
			return cmdCount;
		}

		public void setCmdCount(int cmdCount) {
			this.cmdCount = cmdCount;
		}

		public long getMaxTime() {
			return maxTime;
		}

		public void setMaxTime(long maxTime) {
			this.maxTime = maxTime;
		}

		public long getMinTime() {
			return minTime;
		}

		public void setMinTime(long minTime) {
			this.minTime = minTime;
		}

		public short getMaxCmd() {
			return maxCmd;
		}

		public void setMaxCmd(short maxCmd) {
			this.maxCmd = maxCmd;
		}

		public short getMinCmd() {
			return minCmd;
		}

		public void setMinCmd(short minCmd) {
			this.minCmd = minCmd;
		}

	}
}
